import datetime

from django.db import models

# 入库单
from django.db.models import Max

from base.models import StoreHouse, Category, Unit, CustomSupplier, Goods
from finance.models import CapitalAccount
from sale.models import SaleOrderDetail
from users.models import UserInfo


class WareHouseEntry(models.Model):
    """商品入库单"""
    STATUS = (
        (0, '等待付款'),
        (1, '完全付款'),
    )
    FLAGS = (
        (0, '采购订单'),
        (1, '采购退货'),
        (2, '其他入库'),
        (3, '还回登记'),
    )
    code = models.CharField(verbose_name='入库单编号', max_length=24)
    warehouse_time = models.DateField(verbose_name='入库时间/退货时间', blank=True, null=True)
    supplier = models.ForeignKey(to=CustomSupplier, verbose_name='供应商', blank=True, null=True,
                                 on_delete=models.SET_NULL, db_constraint=False)
    buyer = models.ForeignKey(to=UserInfo, verbose_name='采购员', blank=True, null=True,
                              on_delete=models.SET_NULL, db_constraint=False)
    house = models.ForeignKey(to=StoreHouse, verbose_name='所属仓库', blank=True, null=True,
                              on_delete=models.SET_NULL, db_constraint=False)

    total_amount = models.FloatField(verbose_name='总金额', blank=True, null=True)
    amount = models.FloatField(verbose_name='已付款金额', blank=True, null=True)
    status = models.IntegerField(verbose_name='付款状态', blank=True, null=True, choices=STATUS)
    flag = models.IntegerField(verbose_name='采购入库/采购退货', blank=True, null=True, choices=FLAGS)
    imprest = models.BooleanField(verbose_name='直接付款/直接收款标识', blank=True, null=True)
    account = models.ForeignKey(to=CapitalAccount, verbose_name='付款账号', on_delete=models.DO_NOTHING, blank=True, null=True, db_constraint=False)
    imp_amount = models.FloatField(verbose_name='预付款金额/退回金额', blank=True, null=True)
    remark = models.CharField(verbose_name='备注', max_length=128, blank=True, null=True)
    oper_user = models.ForeignKey(to=UserInfo, verbose_name='操作员', related_name="users", blank=True, null=True,
                                  on_delete=models.SET_NULL, db_constraint=False)
    order_status = models.IntegerField(verbose_name='付款渠道标识', blank=True, null=True)
    update_time = models.DateTimeField(verbose_name='修改时间', auto_now=True)
    add_time = models.DateTimeField(verbose_name='添加时间', auto_now_add=True)

    def __str__(self):
        return self.code

    class Meta:
        verbose_name = '商品入库单'
        verbose_name_plural = verbose_name
        ordering = ["-code"]

    @classmethod
    def get_max_code(cls, flag):
        date = datetime.datetime.now().strftime('%Y%m%d')
        if flag == 0:   # 采购入库
            date = "CGRK{}".format(date)
        elif flag == 1:     # 采购退货
            date = "CGTH{}".format(date)
        elif flag == 2:     # 其他入库
            date = "QTRK{}".format(date)
        elif flag == 3:     # 还回登记
            date = "HHDJ{}".format(date)
        max_code = cls.objects.filter(code__startswith=date).aggregate(max_code=Max("code"))
        max_value = max_code['max_code']
        if max_value is None:
            num = '0001'
            code = '{0}{1}'.format(date, num)
            return code
        else:
            num = str(int(max_value[-4:]) + 1).rjust(4, '0')
            code = '{0}{1}'.format(date, num)
            return code

    def org_instance(self):
        inst = self.__class__.objects.filter(id=self.id).first()
        return inst

    def save(self, *args, **kwargs):
        # 入库单编号
        if self.code == "" or self.code is None:
            self.code = self.__class__.get_max_code(self.flag)
        else:
            if self.id is None:
                exists = self.__class__.objects.filter(code=self.code).exists()
                if exists:
                    self.code = self.__class__.get_max_code(self.flag)

        # # 直接付款和实际付款
        if self.id:
            org = self.org_instance()
            org_imprest = org.imprest
            if org_imprest and self.imprest:
                self.amount += (self.imp_amount - org.imp_amount)
            else:
                if self.imprest:
                    self.amount += self.imp_amount
                elif org_imprest:
                    self.amount -= org.imp_amount
        else:
            if self.imprest:    # 直接付款
                self.amount = self.imp_amount

        if self.amount and abs(self.total_amount) <= abs(self.amount):
            self.status = 1     # 完全付款
        else:
            self.status = 0

        return super().save(*args, **kwargs)


# 入库单明细
class WareHouseEntryDetail(models.Model):
    """入库单明细"""
    goods = models.ForeignKey(to=Goods, on_delete=models.CASCADE, blank=True, null=True, db_constraint=False)
    entry = models.ForeignKey(to=WareHouseEntry, related_name="lists", on_delete=models.CASCADE, blank=True, null=True, db_constraint=False)
    batch_num = models.CharField(verbose_name='批号', max_length=16, blank=True, null=True)
    nums = models.FloatField(verbose_name='入库数量', blank=True, null=True)
    price = models.FloatField(verbose_name='单价', blank=True, null=True)
    total_amount = models.FloatField(verbose_name='金额', blank=True, null=True)
    quantity = models.FloatField(verbose_name='库存数量', blank=True, null=True)
    remark = models.CharField(verbose_name='备注', max_length=128, blank=True, null=True)
    sale_detail = models.ForeignKey(to=SaleOrderDetail, verbose_name='借出记录', blank=True, null=True, on_delete=models.CASCADE, db_constraint=False)
    update_time = models.DateTimeField(verbose_name='修改时间', auto_now=True)
    add_time = models.DateTimeField(verbose_name='添加时间', auto_now_add=True)

    def __str__(self):
        return self.goods.code

    class Meta:
        verbose_name = '入库单明细'
        verbose_name_plural = verbose_name


class WareHouseStats(models.Model):
    """入库统计数据"""
    goods = models.ForeignKey(to=Goods, on_delete=models.CASCADE, blank=True, null=True, db_constraint=False)
    nums = models.FloatField(verbose_name='入库数量', blank=True, null=True)
    total_amount = models.FloatField(verbose_name='金额', blank=True, null=True)
    update_time = models.DateTimeField(verbose_name='修改时间', auto_now=True)
    add_time = models.DateTimeField(verbose_name='添加时间', auto_now_add=True)

    def __str__(self):
        return self.goods.code

    class Meta:
        verbose_name = '入库单明细'
        verbose_name_plural = verbose_name

    def get_avg_price(self):
        if self.nums == 0:
            return 0
        return round(self.total_amount / self.nums, 3)


class PurchasePayOrder(models.Model):
    """采购付款单"""
    FLAGS = (
        (0, '采购订单/退货'),
        (1, '采购直接付款'),
        (2, '退货直接收款'),
    )
    code = models.CharField(verbose_name='付款单编号', max_length=24)
    account = models.ForeignKey(to=CapitalAccount, verbose_name='付款账号', on_delete=models.DO_NOTHING, db_constraint=False)
    pay_time = models.DateField(verbose_name='付款时间', blank=True, null=True)
    supplier = models.ForeignKey(to=CustomSupplier, verbose_name='收款单位', blank=True, null=True,
                                 on_delete=models.SET_NULL, db_constraint=False)
    user = models.ForeignKey(to=UserInfo, verbose_name='付款人', blank=True, null=True,
                             on_delete=models.SET_NULL, db_constraint=False)
    payable = models.FloatField(verbose_name='应付款金额', blank=True, null=True)
    pay_amount = models.FloatField(verbose_name='本次付款金额', blank=True, null=True)
    discount_amount = models.FloatField(verbose_name='优惠金额', blank=True, null=True)
    actual_amount = models.FloatField(verbose_name='实际付款金额', blank=True, null=True)
    oper = models.ForeignKey(to=UserInfo, verbose_name='操作人', related_name="opers", blank=True, null=True,
                             on_delete=models.SET_NULL, db_constraint=False)
    remark = models.CharField(verbose_name='备注', max_length=128, blank=True, null=True)
    flag = models.IntegerField(verbose_name='支付类型', blank=True, null=True, choices=FLAGS)
    entry_code = models.CharField(verbose_name='入库单编号', max_length=24, blank=True, null=True)
    # balance = models.FloatField(verbose_name='余额', blank=True, null=True)
    update_time = models.DateTimeField(verbose_name='修改时间', auto_now=True)
    add_time = models.DateTimeField(verbose_name='添加时间', auto_now_add=True)

    def __str__(self):
        return self.code

    class Meta:
        verbose_name = '采购付款单'
        verbose_name_plural = verbose_name
        ordering = ["-id"]

    @classmethod
    def get_max_code(cls):
        date = datetime.datetime.now().strftime('%Y%m%d')
        date = "CGFK{}".format(date)
        max_code = cls.objects.filter(code__startswith=date).aggregate(max_code=Max("code"))
        max_value = max_code['max_code']
        if max_value is None:
            num = '0001'
            code = '{0}{1}'.format(date, num)
            return code
        else:
            num = str(int(max_value[-4:]) + 1).rjust(4, '0')
            code = '{0}{1}'.format(date, num)
            return code

    def save(self, *args, **kwargs):
        # 付款单编号
        if self.code == "" or self.code is None:
            self.code = self.__class__.get_max_code()
        else:
            if self.id is None:
                exists = self.__class__.objects.filter(code=self.code).exists()
                if exists:
                    self.code = self.__class__.get_max_code()

        return super().save(*args, **kwargs)


class PurchasePayOrderDetail(models.Model):
    """采购付款单明细"""
    pay_order = models.ForeignKey(to=PurchasePayOrder, verbose_name='付款单编号', related_name="details", on_delete=models.CASCADE, blank=True, null=True, db_constraint=False)
    entry = models.ForeignKey(to=WareHouseEntry, verbose_name='采购入库单', on_delete=models.SET_NULL, blank=True, null=True, db_constraint=False)
    pay_amount = models.FloatField(verbose_name='本次付款金额', blank=True, null=True)
    remark = models.CharField(verbose_name='备注', max_length=128, blank=True, null=True)
    doc_type = models.CharField(verbose_name='单价类型', max_length=32, blank=True, null=True)
    update_time = models.DateTimeField(verbose_name='修改时间', auto_now=True)
    add_time = models.DateTimeField(verbose_name='添加时间', auto_now_add=True)

    def __str__(self):
        return self.pay_order.code

    class Meta:
        verbose_name = '采购付款单明细'
        verbose_name_plural = verbose_name
